/*
* @Author: slp
* @Date:   2017-08-02 16:22:08
* @Last Modified by:   slp
* @Last Modified time: 2018-07-05 17:07:54
*/

// #include <config.h>

#define UART_BASE_ADDR 0x13000000

#define ORIGIN_BORAD
#define PL01X

#ifdef ORIGIN_BORAD
#ifdef PL01X

static char * seria_port = (char *)UART_BASE_ADDR;


// typedef unsigned int u32;
/*
 * We can use a combined structure for PL010 and PL011, because they overlap
 * only in common registers.
 */
// struct pl01x_regs {
// 	u32	dr;		/* 0x00 Data register */
// 	u32	ecr;		/* 0x04 Error clear register (Write) */
// 	u32	pl010_lcrh;	/* 0x08 Line control register, high byte */
// 	u32	pl010_lcrm;	/* 0x0C Line control register, middle byte */
// 	u32	pl010_lcrl;	/* 0x10 Line control register, low byte */
// 	u32	pl010_cr;	/* 0x14 Control register */
// 	u32	fr;		/* 0x18 Flag register (Read only) */
// // #ifdef CONFIG_PL011_SERIAL_RLCR
// 	u32	pl011_rlcr;	/* 0x1c Receive line control register */
// // #else
// // 	u32	reserved;
// // #endif
// 	u32	ilpr;		/* 0x20 IrDA low-power counter register */
// 	u32	pl011_ibrd;	/* 0x24 Integer baud rate register */
// 	u32	pl011_fbrd;	/* 0x28 Fractional baud rate register */
// 	u32	pl011_lcrh;	/* 0x2C Line control register */
// 	u32	pl011_cr;	/* 0x30 Control register */
// };
// static struct pl01x_regs *pl01x_port = (struct pl01x_regs *)UART_BASE_ADDR;
#define UART_PL01x_FR_RXFE              0x10
#define UART_PL01x_FR_TXFF              0x20
#define UART_PL01x_FR_PORT		((int*)(seria_port+0x18))
#define UART_PL01x_ECR_PORT		((int*)(seria_port+0x04))
#define UART_PL01x_DR_PORT		((int*)(seria_port))

void _pl01x_init(void *uart_base_addr, int baud_divisor)
{
	seria_port = (char *)uart_base_addr;
#ifdef BOARD_FVP_AEM_BASE
	void UartInit(void *uart_base_addr);
	UartInit(uart_base_addr);
#endif
}


void _pl01x_putc(const char c)
{
	// *seria_port = c;
	// while (pl01x_port->fr & UART_PL01x_FR_TXFF);
	// while ((*(int*)(seria_port + 0x18)) & UART_PL01x_FR_TXFF) ;
	while ((*UART_PL01x_FR_PORT) & UART_PL01x_FR_TXFF) ;
	*seria_port = c;
	if (c == '\n')
		*seria_port = 'm';
		// *seria_port = '\r';
}

char _pl01x_getc()
{
	unsigned int data;
	while ( (*UART_PL01x_FR_PORT) & UART_PL01x_FR_RXFE);
	data = *UART_PL01x_DR_PORT;

	/* check for an error flag */
	if (data & 0xFFFFFF00) {
		// clear the error
		*UART_PL01x_ECR_PORT = 0xFFFFFFFF;
		return -1;
	}
	return (char)data;
}

// static int pl01x_getc (int portnum)
// {
// 	struct pl01x_regs *regs = pl01x_get_regs(portnum);
// 	unsigned int data;

// 	/* Wait until there is data in the FIFO */
// 	while (readl(&regs->fr) & UART_PL01x_FR_RXFE)
// 		WATCHDOG_RESET();

// 	data = readl(&regs->dr);

// 	/* Check for an error flag */
// 	if (data & 0xFFFFFF00) {
// 		/* Clear the error */
// 		writel(0xFFFFFFFF, &regs->ecr);
// 		return -1;
// 	}

// 	return (int) data;
// }

#endif // end pl01x
#endif // end origin board